package com.demo.springcloud.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter;
import org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter;
import org.springframework.cloud.netflix.zuul.filters.pre.*;
import org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter;
import org.springframework.cloud.netflix.zuul.filters.route.SendForwardFilter;
import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 路由与过滤是Zuul的两大核心功能，
 *  路由功能负责将外部请求转发到具体的服务实例上去，是实现统一访问入口的基础，
 *  过滤功能负责对请求过程进行额外的处理，是请求校验过滤及服务聚合的基础。
 *
 * Zuul中有以下几种典型的过滤器类型。
 * pre：在请求被路由到目标服务前执行，比如权限校验、打印日志等功能；
 * routing：在请求被路由到目标服务时执行，这是使用Apache HttpClient或Netflix Ribbon构建和发送原始HTTP请求的地方；
 * post：在请求被路由到目标服务后执行，比如给目标服务的响应添加头信息，收集统计数据等功能；
 * error：请求在其他阶段发生错误时执行。
 *
 * 以下是--前置过滤器，用于在请求路由到目标服务前打印请求日志。
 */
@Component
public class PreLogFilter extends ZuulFilter {
    private Logger LOGGER = LoggerFactory.getLogger(this.getClass());
   /* 过滤器名称				过滤类型		优先级			过滤器的作用

    ServletDetectionFilter pre				-3			检测当前请求是通过DispatcherServlet处理运行的还是ZuulServlet运行处理的。

    Servlet30WrapperFilter pre				-2			对原始的HttpServletRequest进行包装。

    FormBodyWrapperFilter pre                -1          将Content-Type为application/x-www-form-urlencoded或multipart/form-data的请求包装成FormBodyRequestWrapper对象。

    DebugFilter route               1			根据zuul.debug.request的配置来决定是否打印debug日志。

    PreDecorationFilter route				 5			对当前请求进行预处理以便执行后续操作。

    RibbonRoutingFilter route				10          通过Ribbon和Hystrix来向服务实例发起请求，并将请求结果进行返回。

    SimpleHostRoutingFilter route				100			只对请求上下文中有routeHost参数的进行处理，直接使用HttpClient向routeHost对应的物理地址进行转发。

    SendForwardFilter route				500			只对请求上下文中有forward.to参数的进行处理，进行本地跳转。

    SendErrorFilter post				0			当其他过滤器内部发生异常时的会由它来进行处理，产生错误响应。

    SendResponseFilter post				1000		利用请求上下文的响应信息来组织请求成功的响应内容。*/

    /**
     * 过滤器类型，有pre、routing、post、error四种。
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 过滤器执行顺序，数值越小优先级越高。
     */
    @Override
    public int filterOrder() {
        return 1;
    }
    /**
     * 是否进行过滤，返回true会执行过滤。
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }
    /**
     * 自定义的过滤器逻辑，当shouldFilter()返回true时会执行。
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String host = request.getRemoteHost();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        LOGGER.info("Remote host:{},method:{},uri:{}", host, method, uri);
        return null;
    }
}
